﻿#ifndef SVR_COMMON_ASIO_ASIO_SERVER_HEAD__
#define SVR_COMMON_ASIO_ASIO_SERVER_HEAD__

#include <cstdint>  // for uint16_t
#include <unordered_map>
#include <vector>

#include <boost/asio/io_service.hpp>  // for io_service
#include <boost/asio/spawn.hpp>  // for yield_context

#include "rpc/rpc_req_resp_fwd.h"  // for RpcRequest
#include "rpc/rpc_service_sptr.h"  // for RpcServiceSptr
#include "server_type.h"  // for EServerType

class CAsioSvrSession;
class CClientMailBox;
class CRpcCallContext;
class CServerMailBox;
class CWorld;
class CRpcReqHandler;

class CAsioServer
{
public:
	explicit CAsioServer(uint16_t uSvrId, EServerType serverType, CWorld& rWorld);
	virtual ~CAsioServer();

public:
	void Shutdown();

public:
	// 注册服务。
	// sServiceName须包含包名，如"rpc.TestSvc".
	// pService允许为空，表示忽略该服务。
	void RegisterService(const std::string& sServiceName,
		RpcServiceSptr pService);
	void RegisterService(RpcServiceSptr pService);

public:
	void BlockingRun(uint16_t uPort);

public:
	void HandleRpcRequest(uint64_t uRpcCltId, const rpc::RpcRequest& req);
	void HandleRpcRequest(const CRpcCallContext& ctx,
		const std::string& sService, const std::string& sMethod,
		const std::string& sContent);

public:
	// 转发Rpc. 转发后返回true. 目前仅Base有转发功能。
	virtual bool DoForwardRpcRequest(const CRpcCallContext& ctx,
		const std::string& sService, const std::string& sMethod,
		const std::string& sContent) const
	{
		return false;
	};

public:
	//服务器主动关闭一个socket. 以 ClientId 为索引， 即MailBoxId, SessionId.
	void DisconnectClient(uint64_t uClientId);

public:
	void InsertSession(CAsioSvrSession& rSession);
	void EraseSession(CAsioSvrSession& rSession);

private:
	void LoopAccept(unsigned short port, boost::asio::yield_context yield);

public:
	using io_service = boost::asio::io_service;
	inline io_service& GetIoService() { return m_ioService; }
	inline CWorld& GetWorld() { return m_rWorld; }

	inline uint16_t GetServerId() const
	{
		return m_uServerId;
	}

	EServerType GetServerType()
	{
		return m_eServerType;
	}
	CServerMailBox* GetServerMailbox(uint16_t nServerId)
	{
		if (nServerId < m_serverMbs.size())
		{
			return m_serverMbs[nServerId];
		}
		else
		{
			return nullptr;
		}
	}

	CClientMailBox* GetClientMailbox(uint64_t uMbId);

	using SvrMailBoxVec = std::vector<CServerMailBox*>;
	inline SvrMailBoxVec& GetAllServerMbs()
	{
		return m_serverMbs;
	}

private:
	void SpawnS2sSessions();
	CAsioSvrSession* GetSession(uint64_t uSessionId) const;
	virtual void DoSpawnPushPluto() {};

private:
	io_service m_ioService;
	CWorld& m_rWorld;

protected:
	// SessionId -> Session
	std::unordered_map<uint64_t, CAsioSvrSession*> m_mapSessions;
	SvrMailBoxVec m_serverMbs;       //服务器组件的mailbox, 以SvrId为索引
	const uint16_t m_uServerId = 0;  // Cfg.ini 中的ID, 也是命令行中的 ID.
	EServerType   m_eServerType = SERVER_NONE;
	bool m_bShutdown = false;
	std::unique_ptr<CRpcReqHandler> m_pRpcReqHandler;
};

#endif  // SVR_COMMON_ASIO_ASIO_SERVER_HEAD__

